/*
 * Copyright 2020-2025 the original author or authors.
 * You cannot use this file unless authorized by the author.
 */
package org.ipig.proc.fun.obj;

import com.alibaba.fastjson.JSONObject;
import org.ipig.proc.unit.Mergeable;
import org.ipig.proc.unit.ObjectValue;
import org.ipig.proc.unit.Valueable;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

/**
 * 用于平行列表的树形统计计算
 *
 * @author <a href="mailto:comchnts@163.com">chinats</a>
 * @version $$Id: MergeableMapObj.java 14 2020-04-17 06:56:19Z ts <comchnts@163.com> $$
 * @since 1.0
 */
@NoArgsConstructor
public class MergeableMapObj implements Mergeable, ObjectValue<Map, JSONObject>, Serializable {
    @Getter
    private Long count = 0L;//计数
    @Getter
    @Setter
    private boolean merged = true;
    @Getter
    private Map<Object, Mergeable> value = new HashMap<>();

    public MergeableMapObj(Object key, Mergeable inMergeable) {
        Mergeable mergeable = value.get(key);
        if (mergeable != null) {
            mergeable.merge(inMergeable);
        } else {
            value.put(key, inMergeable);
        }
        count++;
    }

    @Override
    public Mergeable merge(Mergeable mergeable) {
        if (mergeable instanceof MergeableMapObj) {
            MergeableMapObj newMergeableObject = (MergeableMapObj) mergeable;
            for (Map.Entry<Object, Mergeable> entry : newMergeableObject.value.entrySet()) {
                Object key = entry.getKey();
                Mergeable newMergeable = entry.getValue();
                Mergeable oldMergeable = value.get(key);
                if (oldMergeable != null) {
                    oldMergeable.merge(newMergeable);
                } else {
                    this.value.put(key, newMergeable);
                }
            }
            this.count = this.count + newMergeableObject.count;
        } else {
            throw new UnsupportedOperationException("Cannot merge " + this.getClass().getName() + " with " + mergeable.getClass().getName());
        }
        return this;
    }

    @Override
    public Mergeable deepClone() {
        MergeableMapObj mergeable = new MergeableMapObj();
        mergeable.count = this.count;
        mergeable.value = this.value;
        mergeable.setMerged(this.merged);
        return mergeable;
    }

    @Override
    public JSONObject getObjValue() {
        JSONObject jsonObj = new JSONObject();
        for (Map.Entry<Object, Mergeable> entry : value.entrySet()) {
            Mergeable value = entry.getValue();
            Object key = entry.getKey();
            if (value instanceof Valueable && value != null && key != null) {
                jsonObj.put(key.toString(), ((Valueable) value).getValue());
            }
        }
        return jsonObj;
    }
}